<?php

namespace Xrfg\Wallet\ETH\Console;

use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use phpseclib\Math\BigInteger;
use App\Models\Coin;
use App\Models\Recharge as RechargeModel;
use App\Models\Account;
use Xrfg\Wallet\Common\Jobs\RechargeJob;
use Xrfg\Wallet\ETH\Services\ETHWallet;
use Xrfg\Wallet\ETH\Traits\ETHHelper;

class RechargeETH extends Command
{
    use ETHHelper;

    protected $signature = 'recharge:eth';

    protected $description = 'ETH 充值';

    protected $times = 0;

    protected $coinId;

    protected $rpc;

    protected $blockNumber;

    public function __construct()
    {
        parent::__construct();

        $this->rpc = new ETHWallet(config('wallet.eth.node.rpc'));
    }

    public function handle()
    {
        if (!$this->coinId) {
            $this->coinId = Coin::where('name', 'ETH')->value('id');
        }

        ++$this->times;
        if ($this->times >= 100) {
            return;
        }
        $this->info('times:'.$this->times);
        $this->blockNumber = Cache::get('ETH:blockNumber', 7866157);
        try {
            $result = $this->rpc->eth_blockNumber();
            $blockNumber = new BigInteger($result, 16);
            $this->info('latest:'.$blockNumber->toString());
            if ($blockNumber->toString() - 12 <= $this->blockNumber) {
                self::handle();

                return;
            }
            $this->info('current:'.$this->blockNumber);
            $this->info('scanning:'.($this->blockNumber + 1));
            $block = $this->rpc->eth_getBlockByNumber($this->num2hex($this->blockNumber + 1), true);
            $transactions = collect($block['transactions'])
                ->where('to', '!=', null)
                ->where('value', '!=', '0x0');
            $transactions->each(function ($tx) {
                $hash = $tx['hash'];
                $address = $tx['to'];
                $number = $this->wei2ether($tx['value']);

                $isAccountExists = Account::where('coin_id', $this->coinId)
                    ->where('address', $address)
                    ->exists();
                // 检查地址
                if ($isAccountExists) {
                    $isRechargeExists = RechargeModel::where('hash', $hash)->exists();
                    // 检查hash
                    if (!$isRechargeExists) {
                        // 检查 from
                        if ($tx['from'] != config('wallet.eth.withdraw_address')) {
                            RechargeJob::dispatch($this->coinId, $hash, $number, $address)
                                ->onQueue('recharge');
                        }
                    }
                }
            });
            Cache::forever('ETH:blockNumber', $this->blockNumber + 1);
            self::handle();
        } catch (Exception $exception) {
            Log::error($exception);
            self::handle();
        }
    }
}
